# ifndef _ARBOL_B_MAS_H_
# define _ARBOL_B_MAS_H_

/********************************************************************
 * IndiceBMas.h
 * 
 * Descripcion :implementacion de arbol B mas.
*********************************************************************/

#include "nodo_b_mas.h"
#include "arch_bloques_libres.h"
#include "arbol_b.h"

class ArbolBMas : public ArbolB {
	
	private:
	
		unsigned int _nodo_actual_;
		TipoDato* _clave_actual_;
		
		/*
 		 * Maneja el underflow. Primero intenta redistribuir elementos
 		 * y si esto no se puede, concatena nodos.
 		 * Recibe el padre y el hijo que produjo el underflow. Tambien
 		 * si este ultimo era el hijo derecho o izquierdo.
 		 */ 
 		void manejar_underflow( Nodo * nodo, Nodo * hijo, bool hijo_derecho );
 		
		/*
		 * Maneja el overflow para todos los nodos menos la raiz. Resuelve
		 * la propagacion sin llegar a esta.
		 */ 
		bool manejar_overflow(Nodo * padre, Nodo * Hijo, ElemNodo * elem);
		
		// maneja el overflow del nodos de nivel 0, las hojas, que son parte del set secuencial
		bool manejar_overflow_hoja(Nodo * padre, Nodo * hijo, ElemNodo * elem);

		/*
		 * Metodo que en forma recursiva consulta por la existencia de un
		 * elemento. En retorno devuelve el dato si lo encontro, o el del
		 * mayor de los menores, NULL en caso contrario.
		 */ 
		void consultar_interno(Nodo * nodo, TipoDato * clave, TipoInt ** retorno );
		
		/*
		 * Metodo que en forma recursiva consulta por la existencia de un
		 * elemento. En retorno devuelve el dato si lo encontro,
		 * NULL en caso contrario.
		 */ 
		void consultar_interno_exacto(Nodo * nodo, TipoDato * clave, TipoInt ** retorno );
		
		void concatenar_hoja(Nodo * nodo, Nodo * hijo, bool hijo_derecho);
		
 		//lo usa el concatenar hoja, si no no lo uses, no guarda bloques
 		void concat_interno(NodoBMas* izq, NodoBMas* der, Nodo* padre);
 		
 		bool redistribuir_hoja( Nodo * nodo, Nodo * hijo, bool hijo_derecho );
 		
 		/*
 		 * cambia el separador en el nivel 1 del arbol porque en el nodo (hijo derecho)
 		 * se produjo un cambio en el primer elemento , actualiza la clave anterior del padre
 		 */
 		void cambiar_claves(Nodo * nodo,Nodo * padre);
		
		/*
 		 * Le saca un elemento a la hoja vecina, es decir el vecino.  
 		 * Esto lo realiza si no queda en underflow el vecino.
 		 * El intercambio es entre las hojas, el padre solo los conecta, no realiza intercambio
 		 */ 
 		bool equilibrar_hojas(Nodo * hijo, Nodo * vecino );
		
		/*
		 * dado el nodo padre, se intercambia la clave vieja por la nueva
		 */
		void actualizar_clave(Nodo* padre,TipoDato* claveVieja,TipoDato* claveNueva);
 		
		/*
		 * Redefinicion del quitar interno de arbol B, para actualizar el elemento
		 * del padre si el primero del nodo cambio.
		 */
		virtual bool quitar_interno(Nodo * nodo, TipoDato * clave, void ** param = NULL);
		
		void verif_cambio_clave (Nodo * nodo, TipoDato * clave, void ** param);
		
		void cambiar_clave_padre (Nodo * nodo, void ** param);
		
		bool quitar(TipoDato* clave) throw(ExcepArchCerrado,ExcepErrorTipos,  ExcepLeerBloque);
		
		/*
		 * Maneja el overflow de la raiz.
		 */ 
		void overflow_en_raiz(Nodo * raiz, ElemNodo * elem);

	public:
	
		ArbolBMas(std::string nombre, unsigned int tam_bloque);
	
		~ArbolBMas();
		
		/*
		 * Get Siguiente: Devuelve el dato del elemento siguiente en el indice al
		 * recien consultado, segun el orden creciente secuencial.
		 * Si era el ultimo devuelve NULL.
		 */
		 TipoInt* get_siguiente();
		 
		 /*
		 * Devuelve el contenido que se encuentra acompañando a la clave
		 * en el indice. En caso de no existir devuelve NULL.
		 */
		TipoInt * consultar_exacto(TipoDato * clave) throw(ExcepArchCerrado,ExcepLeerBloque);
		
};

#endif
